package com.example.demo.use_demo.a_excel_demo;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;

import java.util.*;
import java.util.function.Consumer;

/**
 * 数据转换器
 *
 * @author zhangqiang
 * @date 2021/6/1 20:39
 */
public class ExcelDataConverter<S> {

    private ExcelDataConverter() {
    }

    /**
     * 转换规则
     */
    private final Map<String, Map<?, ?>> fieldKeyConvertDataMap = new HashMap<>();
    /**
     * 自定义转换规则
     */
    private final List<Consumer<S>> customConvertConsumerList = new ArrayList<>();

    /**
     * 获取Validator
     */
    public static <S> ExcelDataConverter<S> newConverter(Class<S> entityClass) {
        return new ExcelDataConverter<S>();
    }

    /**
     * 包装转换规则
     *
     * @param sourceData 源数据
     * @param fieldKeys  要转换的属性
     * @return this
     */
    public ExcelDataConverter<S> wrapConvert(Map<?, ?> sourceData, Collection<String> fieldKeys) {
        for (String fieldKey : fieldKeys) {
            fieldKeyConvertDataMap.put(fieldKey, sourceData);
        }
        return this;
    }

    /**
     * 包装转换规则
     *
     * @param sourceData 源数据
     * @param fieldKeys  要转换的属性
     * @return this
     */
    public ExcelDataConverter<S> wrapConvert(Map<?, ?> sourceData, String... fieldKeys) {
        return this.wrapConvert(sourceData, Arrays.asList(fieldKeys));
    }

    /**
     * 自定义转换
     *
     * @param consumer 自定义转换逻辑
     * @return this
     */
    public ExcelDataConverter<S> wrapConvertWithCustomConsumer(Consumer<S> consumer) {
        customConvertConsumerList.add(consumer);
        return this;
    }

    /**
     * 数单条据转换
     *
     * @param data 数据
     */
    public void convertWithCustomConsumer(S data) {
        for (Consumer<S> consumer : customConvertConsumerList) {
            consumer.accept(data);
        }
    }

    /**
     * 单个数据转换
     *
     * @param fieldKey   属性名
     * @param fieldValue 要转换的值
     * @param <V>        值类型
     * @return 结果值
     */
    @SuppressWarnings(value = "unchecked")
    public <K extends String, V> V convertField(K fieldKey, V fieldValue) {
        if (fieldKeyConvertDataMap.containsKey(fieldKey)) {
            return (V) fieldKeyConvertDataMap.get(fieldKey).get(fieldValue);
        }
        return fieldValue;
    }

    /**
     * 单条数据转换
     *
     * @param data 数据
     */
    @SuppressWarnings(value = "unchecked")
    public <V> void convertFields(Map<String, V> data) {
        if (this.hasFieldsConvert()) {
            fieldKeyConvertDataMap.forEach((k, v) -> {
                data.replace(k, this.convertField(k, data.get(k)));
            });
        }
        if (this.hasCustomConvertConsumer()) {
            this.convertWithCustomConsumer((S) data);
        }
    }

    /**
     * 单条数据转换
     *
     * @param data 数据
     */
    public void convertFields(S data) {
        if (this.hasFieldsConvert()) {
            fieldKeyConvertDataMap.forEach((k, v) -> {
                ReflectUtil.setFieldValue(data, k, this.convertField(k, ReflectUtil.getFieldValue(data, k)));
            });
        }
        if (this.hasCustomConvertConsumer()) {
            this.convertWithCustomConsumer(data);
        }
    }

    /**
     * 是否有需要转换的key
     */
    public boolean hasFieldsConvert() {
        return CollectionUtil.isNotEmpty(fieldKeyConvertDataMap);
    }

    /**
     * 是否有自定义转换器
     */
    public boolean hasCustomConvertConsumer() {
        return CollectionUtil.isNotEmpty(customConvertConsumerList);
    }

}
